package com.boot.admin.modules.sys.ai.service;

import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.boot.admin.modules.sys.ai.config.XfyunAiConfig;
import com.boot.admin.modules.sys.ai.model.entity.AiRole;
import lombok.extern.slf4j.Slf4j;
import okhttp3.*;
import org.springframework.stereotype.Service;
import org.springframework.util.Base64Utils;

import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;
import java.util.TimeZone;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.TimeUnit;

/**
 * 讯飞TTS流式合成服务
 *
 * @author 李飞洋
 * @date 2025/9/24
 */
@Slf4j
@Service
public class XfyunTtsStreamService {

    private final XfyunAiConfig xfyunAiConfig;
    private final OkHttpClient httpClient;

    public XfyunTtsStreamService(XfyunAiConfig xfyunAiConfig) {
        this.xfyunAiConfig = xfyunAiConfig;
        this.httpClient = new OkHttpClient.Builder()
                .connectTimeout(10, TimeUnit.SECONDS)
                .writeTimeout(60, TimeUnit.SECONDS)
                .readTimeout(60, TimeUnit.SECONDS)
                .build();
    }

    /**
     * WebSocket流式音频合成
     */
    public void generateAudioStream(String text, AiRole role, RealtimeVoiceService.TtsStreamCallback callback) {
        CompletableFuture.runAsync(() -> {
            WebSocket webSocket = null;
            try {
                if (text == null || text.trim().isEmpty()) {
                    callback.onError("文本内容为空");
                    return;
                }

                // 对于过短的文本，跳过TTS处理
                if (text.trim().length() < 2) {
                    log.debug("文本过短，跳过TTS处理: {}", text);
                    callback.onComplete();
                    return;
                }

                log.debug("开始讯飞TTS WebSocket流式合成，文本: {}", text);

                // 构建WebSocket认证URL
                String authUrl = buildAuthUrl();

                // 创建WebSocket连接
                Request request = new Request.Builder()
                        .url(authUrl)
                        .build();

                TtsWebSocketListener listener = new TtsWebSocketListener(text, role, callback);
                webSocket = httpClient.newWebSocket(request, listener);

                // 等待连接建立
                Thread.sleep(100);

            } catch (Exception e) {
                log.error("讯飞TTS WebSocket连接失败", e);
                callback.onError("TTS WebSocket连接失败: " + e.getMessage());
                if (webSocket != null) {
                    webSocket.close(1000, "Connection error");
                }
            }
        });
    }

    /**
     * 批量音频合成（用于小文本片段的高效处理）
     */
    public void generateAudioBatch(String text, AiRole role, RealtimeVoiceService.TtsStreamCallback callback) {
        // 直接使用流式合成
        generateAudioStream(text, role, callback);
    }

    /**
     * 快速音频合成（用于小文本片段）
     */
    public void generateQuickAudio(String text, AiRole role, RealtimeVoiceService.TtsStreamCallback callback) {
        generateAudioStream(text, role, callback);
    }

    /**
     * 构建认证URL
     */
    private String buildAuthUrl() throws Exception {
        // 生成RFC1123格式的时间戳
        SimpleDateFormat sdf = new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss z", Locale.US);
        sdf.setTimeZone(TimeZone.getTimeZone("GMT"));
        String date = sdf.format(new Date());
        
        // 构建签名原始字符串
        String host = "tts-api.xfyun.cn";
        String requestLine = "GET /v2/tts HTTP/1.1";
        String signatureOrigin = "host: " + host + "\n" + "date: " + date + "\n" + requestLine;
        
        // 使用HMAC-SHA256计算签名
        Mac mac = Mac.getInstance("HmacSHA256");
        SecretKeySpec spec = new SecretKeySpec(xfyunAiConfig.getApiSecret().getBytes(StandardCharsets.UTF_8), "HmacSHA256");
        mac.init(spec);
        byte[] signed = mac.doFinal(signatureOrigin.getBytes(StandardCharsets.UTF_8));
        String signature = Base64Utils.encodeToString(signed);
        
        // 构建authorization原始字符串
        String authorizationOrigin = String.format(
                "api_key=\"%s\", algorithm=\"%s\", headers=\"%s\", signature=\"%s\"",
                xfyunAiConfig.getApiKey(), "hmac-sha256", "host date request-line", signature
        );
        
        // Base64编码authorization
        String authorization = Base64Utils.encodeToString(authorizationOrigin.getBytes(StandardCharsets.UTF_8));
        
        // 构建完整URL
        return String.format("%s?authorization=%s&date=%s&host=%s",
                xfyunAiConfig.getTtsWsUrl(),
                URLEncoder.encode(authorization, StandardCharsets.UTF_8.name()),
                URLEncoder.encode(date, StandardCharsets.UTF_8.name()),
                URLEncoder.encode(host, StandardCharsets.UTF_8.name())
        );
    }

    /**
     * 确定讯飞语音类型
     */
    private String determineVoiceType(String voiceId) {
        if (voiceId == null || voiceId.trim().isEmpty()) {
            return xfyunAiConfig.getDefaultVoice();
        }

        // 如果已经是讯飞格式的voiceId，直接使用
        if (isXfyunVoice(voiceId)) {
            return voiceId;
        }

        // 根据自定义voiceId映射到讯飞的语音类型
        switch (voiceId.toLowerCase()) {
            case "male_voice_1":
            case "male":
                return "xiaoyu";  // 讯飞男声
            case "female_voice_1":
            case "female":
            default:
                return "xiaoyan"; // 讯飞女声
        }
    }

    /**
     * 检查是否是讯飞的语音ID
     */
    private boolean isXfyunVoice(String voiceId) {
        String[] xfyunVoices = {"xiaoyan", "xiaoyu", "xiaofeng", "xiaoqi", "vinn", "nannan", "catherine"};
        for (String voice : xfyunVoices) {
            if (voice.equals(voiceId)) {
                return true;
            }
        }
        return false;
    }

    /**
     * TTS WebSocket监听器
     */
    private class TtsWebSocketListener extends WebSocketListener {
        private final String text;
        private final AiRole role;
        private final RealtimeVoiceService.TtsStreamCallback callback;

        public TtsWebSocketListener(String text, AiRole role, RealtimeVoiceService.TtsStreamCallback callback) {
            this.text = text;
            this.role = role;
            this.callback = callback;
        }

        @Override
        public void onOpen(WebSocket webSocket, Response response) {
            log.debug("讯飞TTS WebSocket连接已建立");
            try {
                // 发送TTS请求
                sendTtsRequest(webSocket);

            } catch (Exception e) {
                log.error("发送讯飞TTS请求失败", e);
                callback.onError("发送TTS请求失败: " + e.getMessage());
            }
        }

        @Override
        public void onMessage(WebSocket webSocket, String text) {
            log.debug("收到讯飞TTS文本消息: {}", text);
            try {
                JSONObject response = JSONUtil.parseObj(text);

                // 检查错误
                int code = response.getInt("code", 0);
                if (code != 0) {
                    String message = response.getStr("message", "未知错误");
                    log.error("讯飞TTS返回错误: code={}, message={}", code, message);
                    callback.onError("TTS合成错误: " + message);
                    return;
                }

                // 提取音频数据
                JSONObject data = response.getJSONObject("data");
                if (data != null) {
                    String audioBase64 = data.getStr("audio");
                    int status = data.getInt("status", 0);

                    if (audioBase64 != null && !audioBase64.isEmpty()) {
                        byte[] audioChunk = Base64Utils.decodeFromString(audioBase64);
                        if (audioChunk.length > 0) {
                            callback.onAudioChunk(audioChunk);
                        }
                    }

                    // 检查是否完成
                    if (status == 2) {  // status=2表示合成完成
                        callback.onComplete();
                        webSocket.close(1000, "Synthesis complete");
                    }
                }

            } catch (Exception e) {
                log.error("解析讯飞TTS文本消息失败", e);
            }
        }

        @Override
        public void onFailure(WebSocket webSocket, Throwable t, Response response) {
            log.error("讯飞TTS WebSocket连接失败", t);
            callback.onError("WebSocket连接失败: " + t.getMessage());
        }

        @Override
        public void onClosed(WebSocket webSocket, int code, String reason) {
            log.debug("讯飞TTS WebSocket连接已关闭: {} - {}", code, reason);
        }

        /**
         * 发送TTS请求
         */
        private void sendTtsRequest(WebSocket webSocket) throws Exception {
            JSONObject request = new JSONObject();

            // 公共参数
            JSONObject common = new JSONObject();
            common.put("app_id", xfyunAiConfig.getAppId());
            request.put("common", common);

            // 业务参数
            JSONObject business = new JSONObject();
            business.put("aue", "raw");  // 音频编码格式
            business.put("vcn", determineVoiceType(role != null ? role.getVoiceId() : null));  // 发音人
            business.put("speed", role != null && role.getSpeakingRate() != null ? 
                        (int)(role.getSpeakingRate() * 100) : xfyunAiConfig.getDefaultSpeed());  // 语速
            business.put("volume", xfyunAiConfig.getDefaultVolume());  // 音量
            business.put("pitch", role != null && role.getPitch() != null ? 
                         role.getPitch() + 50 : xfyunAiConfig.getDefaultPitch());  // 音高
            business.put("tte", "UTF8");  // 文本编码
            request.put("business", business);

            // 数据参数
            JSONObject data = new JSONObject();
            data.put("status", 2);  // 固定为2（一次性传输）
            data.put("text", Base64Utils.encodeToString(text.getBytes(StandardCharsets.UTF_8)));
            request.put("data", data);

            webSocket.send(request.toString());
            log.debug("发送讯飞TTS请求: {}", request.toString());
        }
    }
}